﻿using System.Collections.Generic;
using UBlockly.Compotent;
using UBlockly.UI;
using UnityEngine;

namespace UBlockly.Sys
{
    public class PainttingSystem
    {
        private UBlockEntry blockEntry;
        private Transform rootTransformForNode;
        readonly uint painttingOffen = 3;
        bool isDuringPaintting = false;
        bool operateSlotTypeOrPackType = false;  //true : slot ; false : pack
        uint frameCount = 0;
        List<NSlotPair> beCheckingSortList = new List<NSlotPair>();

        public PainttingSystem(UBlockEntry entry)
        {
            blockEntry = entry;
            rootTransformForNode = entry.BlockPhysic.NodeRootTransform;
        }
        public void HandlerBlock(BlockObject block)
        {
            BeforePaintting(block);
        }

        public void HandlerOver(BlockObject block)
        {
            AfterPaintting(block);
        }

        void BeforePaintting(BlockObject block)
        {
            isDuringPaintting = true;
            operateSlotTypeOrPackType = block.Node.Value.Scriptable.ResultType == Scriptable.ILVarType.VoidR;
            UBlockExtension.SetToTop(block.Node);
            if (operateSlotTypeOrPackType)
            {
                HandlerSlotEnvironment(block);
            }
            else
            {
                HandlerPackEnvironment(block);
            }
        }

        void AfterPaintting(BlockObject block)
        {
            isDuringPaintting = false;
            if (operateSlotTypeOrPackType)
            {
                BackSlotEvironment(block);
                if (isChecked)
                {
                    Debug.LogError($"id1:{pair1},id2:{pair2}");
                    var target = blockEntry.SpaceSystem.FindNode(pair1).Block;
                    blockEntry.BlockSystem.DoSlot(target, blockEntry.SpaceSystem.FindNode(pair2).Block);
                    blockEntry.NodeHandlerSystem.SlotNodeHandler(target);
                }
            }
            else
            {
                if (targetPackBlock != null && targetPack != null)
                {
                    blockEntry.BlockSystem.DoPack(targetPackBlock, targetPack, packIndex);
                    blockEntry.NodeHandlerSystem.PackNodeHandler(targetPackBlock);
                }
                BackPackEvironment(block);
            }
        }

        void HandlerSlotEnvironment(BlockObject block)
        {
            Debug.Log($"{block.Node.Value.Id}被拖动，链长-{block.Node.List.Count},链头-{block.Node.List.First.Value.Id}");
            bool isBreak = false;
            var list = (block.Node.List as ULinkedList<Node>)?.Split(block.Node.Value, rootTransformForNode,ref isBreak);
            if (isBreak)
            {
                blockEntry.NodeHandlerSystem.DeslotNodeHandler(block);
            }
            list.ForEachCircle(node =>
            {
                node.Block.GetSlotPair().MuteAllRect();
            });
            list.First.Value.Block.GetSlotPair().ActiveARect(true);
            //list.Last.Value.Block.GetSlotPair().ActiveBRect(true);
            beCheckingSortList.Clear();
            beCheckingSortList.Add(list.First.Value.Block.GetSlotPair());
            beCheckingSortList.Add(list.Last.Value.Block.GetSlotPair());
            UBlockExtension.HandlerBeginDragBlock(block);
        }

        void BackSlotEvironment(BlockObject block)
        {
            //1，把第一个节点下所有节点还原
            UBlockExtension.HandlerEndDragBlock(block);
            block.Node.List.ForEachCircle(node =>
            {
                node.Block.GetSlotPair().MuteAllRect(false);
            });
        }

        void HandlerPackEnvironment(BlockObject block)
        {
            targetPackBlock = block as PackTypeBlock;
            var list = blockEntry.BlockSystem.packerList;
            foreach (var nodePacker in list)
            {
                var paramPacker = nodePacker.FindParamPacker(x => x == block.Node.Value.Id);
                if (paramPacker != null) //找到了block所在的paramPacker
                {
                    var node = nodePacker.UnPackNode((int)paramPacker.ParamIndex);
                    if (node != null)
                    {
                        node.Block.UnAttach(rootTransformForNode);
                    }
                    blockEntry.NodeHandlerSystem.DepackNodeHandler(block);
                }
            }
        }

        void BackPackEvironment(BlockObject block)
        {
            targetPack = null;
            targetPackBlock = null;
            targetPackList.Clear();
            packIndex = -1;
        }

        bool isChecked = false;
        long pair1, pair2;
        void DuringSlotPaintting()
        {
            isChecked = false;
            foreach (var checkpair in beCheckingSortList)
            {
                var list = blockEntry.BlockSystem.slotTypeBlockList;
                foreach (var becheck in list)
                {
                    var beCheckPair = becheck.Node.Value.Block.GetSlotPair();
                    if (checkpair.NodeId == beCheckPair.NodeId)
                        continue;
                    //Debug.Log($"正在检测{checkpair.NodeId} - {beCheckPair.NodeId}");
                    if (isChecked = checkpair.ARect.gameObject.activeSelf && beCheckPair.BRect.gameObject.activeSelf &&
                        UBlockExtension.IsRecttransAcross(checkpair.ARect, beCheckPair.BRect))
                    {
                        pair1 = checkpair.NodeId;
                        pair2 = beCheckPair.NodeId;
                    }

                    #region 是否可以反过来
                    //                        if (!isChecked)
                    //                        {
                    //                            if (isChecked = UBtil.IsRecttransAcross(checkpair.BRect, beCheckPair.ARect))
                    //                            {
                    //                                pair1 = checkpair;
                    //                                pair2 = beCheckPair;
                    //                            }
                    //                        }
                    #endregion
                    if (isChecked)
                    {
                        return;
                    }              
                }
            }
        }

        PackerObject targetPack;
        PackTypeBlock targetPackBlock;
        List<PackerObject> targetPackList = new List<PackerObject>();
        int packIndex;
        void DuringPackPaintting()
        {
            targetPackList.Clear();
            targetPack = null;
            var list = blockEntry.BlockSystem.packerList;
            foreach (var becheck in list)
            {
                var paramPackers = becheck.GetParamObjects();
                for (int i = 0; i < paramPackers.Count; i++)
                {
                    var rectPacker = paramPackers[i];
                    var packer = rectPacker.GetPacker();
                    uint packerCode = packer.VarTypeCode;
                    if (packer.ParamType != targetPackBlock.PackType || (packerCode != 0 && packerCode != targetPackBlock.PackTypeCode))
                        continue;
                    if (isChecked = UBlockExtension.IsAcross(packer.BlockAnchor.RectTransform,
                        targetPackBlock.RectTransform.position + new Vector3(0,targetPackBlock.RectTransform.sizeDelta.y/2f)))
                    {
                        Debug.Log($"pack 已经匹配上,index:{i}");
                        packIndex = i;
                        targetPackList.Add(becheck);
                    }
                }
            }

            if (targetPackList.Count != 0)
            {
                CheckPackList(packIndex);
                targetPack = targetPackList[0];
            }
        }

        void CheckPackList(int packIndex)
        {
            foreach (var pack in targetPackList)
            {
                if (pack.PackerCount < packIndex)
                    targetPackList.Remove(pack);
            }
            if(targetPackList.Count > 1)
                targetPackList.Sort(TopPack);
        }

        int TopPack(PackerObject a, PackerObject b)
        {
            if (a.GetParamObject(packIndex).transform.position.z > b.GetParamObject(packIndex).transform.position.z)
                return -1;
            return 1;
        }

        GameObject tempSlotTypeGo;
        public void UpdateDo()
        {
            if (!isDuringPaintting) return;
            if (++frameCount % painttingOffen == 0)
            {
                isChecked = false;
                if (operateSlotTypeOrPackType)
                {
                    if (tempSlotTypeGo != null)
                        GameObject.DestroyImmediate(tempSlotTypeGo);

                    DuringSlotPaintting();
                    if (isChecked) //
                    {

                    }
                }
                else
                {
                    DuringPackPaintting();
                    if (isChecked)
                    {

                    }
                }
            }
        }
    }
}
